package com.demo.config;

import java.util.concurrent.ThreadPoolExecutor;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.task.TaskExecutor;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;

//表示这是个配置类
@Configuration	
public class ExecutorConfig {
	
	@Value("${async.executor.thread.core_pool_size}")  //@Value注解，会从配置文件中读取参数值，赋值给该属性
	private int corePoolSize ; // 核心线程数
	
	@Value("${async.executor.thread.max_pool_size}")
	private int maxPoolSize ; // 最大线程数
	
	@Value("${async.executor.thread.queue_capacity}")
	private int queueCapacity;    //队列容量
	
	@Value("${async.executor.thread.keepalive_seconds}")
	private int keepAliveSeconds;    //线程活跃时间（秒）
	
	@Value("${async.executor.thread.name_prefix}")
	private String namePrefix;    //线程名称前缀
	
	//定义bean，由spring容器管理，id=“taskExecutor” 【多个线程池的情况下，可以指定名称，如：@Bean(name="asyncExecutor")】
	@Bean 
	public TaskExecutor taskExecutor() {
		// 自定义的ThreadPoolTaskExecutor子类（在每次提交线程的时候都会将当前线程池的运行状况打印出来）
		ThreadPoolTaskExecutor executor = new VisiableThreadPoolTaskExecutor(); 
//		ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
		executor.setCorePoolSize(this.corePoolSize); // 配置核心线程数
		executor.setMaxPoolSize(this.maxPoolSize); // 配置最大线程数
		executor.setQueueCapacity(this.queueCapacity); // 配置队列大小
		executor.setKeepAliveSeconds(this.keepAliveSeconds); // 配置线程存活时间
		executor.setThreadNamePrefix(this.namePrefix); // 配置线程名称前缀
		
		// 设置拒绝策略
		//executor.setRejectedExecutionHandler方法，设置拒绝策略
	    //1）若不设置，当 并发请求数 > 最大线程数+队列容量，直接抛出 java.util.concurrent.RejectedExecutionException
	    //2）若设置，则可以选择不同策略
	    //    ①  CALLER_RUNS：不在新线程中执行任务，而是由调用者所在的线程来执行（不建议使用，因为由主线程做耗时操作，当前系统所有线程存在被耗尽堵死的风险）
//		executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy()); 
		
		// 执行初始化
		executor.initialize();
		return executor ;
	}

}
